import json

from django.conf import settings
from django.shortcuts import render_to_response

from rest_framework.response import Response
from rest_framework.viewsets import GenericViewSet

from djcelery.models import PeriodicTask, CrontabSchedule

from XApiTestServer.pagination import MyPageNumberPagination
from XApiTestServer.serializers import PeriodicTaskSerializer
from XApiTestServer.utils.common import *
from XApiTestServer.utils import response
from XApiTestServer.utils.task_opt import CELERY_TEST_TASK, task_value_to_key

import logging


logger = logging.getLogger('XApiTestServer')
# TODO

def create_task(name, task, task_args, crontab_time, desc):
    '''
    新增定时任务
    :param name: 定时任务名称
    :param task: 对应tasks里已有的task
    :param task_args: list 参数
    :param crontab_time: 时间配置
    :param desc: 定时任务描述
    :return: ok
    '''
    # task任务， created是否定时创建
    task, created = celery_models.PeriodicTask.objects.get_or_create(name=name, task=task)
    # 获取 crontab
    crontab = celery_models.CrontabSchedule.objects.filter(**crontab_time).first()
    if crontab is None:
        # 如果没有就创建，有的话就继续复用之前的crontab
        crontab = celery_models.CrontabSchedule.objects.create(**crontab_time)
    task.crontab = crontab  # 设置crontab
    task.enabled = True  # 开启task
    task.kwargs = json.dumps(task_args, ensure_ascii=False)  # 传入task参数
    task.description = desc
    task.save()
    return 'ok'

def task_logic(**kwargs):
    """
    定时任务逻辑处理
    :param kwargs: dict: 定时任务数据
    :return:
    """
    if 'task' in kwargs.keys():
        if kwargs.get('task').get('type') == 'module':
            return load_modules(**kwargs.pop('task'))
        else:
            return load_testsuites(**kwargs.pop('task'))
    if kwargs.get('name') is '':
        return '任务名称不可为空'
    elif kwargs.get('project') is '':
        return '请选择一个项目'
    elif kwargs.get('crontab_time') is '':
        return '定时配置不可为空'
    elif not kwargs.get('module'):
        kwargs.pop('module')

    try:
        crontab_time = kwargs.pop('crontab_time').split(' ')
        if len(crontab_time) > 5:
            return '定时配置参数格式不正确'
        crontab = {
            'day_of_week': crontab_time[-1],
            'month_of_year': crontab_time[3],  # 月份
            'day_of_month': crontab_time[2],  # 日期
            'hour': crontab_time[1],  # 小时
            'minute': crontab_time[0],  # 分钟
        }
    except Exception:
        return '定时配置参数格式不正确'
    if PeriodicTask.objects.filter(name__exact=kwargs.get('name')).count() > 0:
        return '任务名称重复，请重新命名'
    desc = " ".join(str(i) for i in crontab_time)
    name = kwargs.get('name')
    mode = kwargs.pop('mode')

    if 'module' in kwargs.keys():
        kwargs.pop('project')

        if mode == '1':
            return create_task(name, 'XApiTestServer.tasks.module_hrun', kwargs, crontab, desc)
        else:
            kwargs['suite'] = kwargs.pop('module')
            return create_task(name, 'XApiTestServer.tasks.suite_hrun', kwargs, crontab, desc)
    else:
        return create_task(name, 'XApiTestServer.tasks.project_hrun', kwargs, crontab, desc)

def format_json(value):
    try:
        return json.dumps(value, indent=4, separators=(',', ': '), ensure_ascii=False)
    except:
        return value


class Task(object):
    """
    定时任务操作
    """

    def __init__(self, **kwargs):
        logger.info("before process task data:\n {kwargs}".format(kwargs=format_json(kwargs)))
        self.__name = kwargs["name"]
        self.__args = kwargs.get("data", [])

        self.__crontab = kwargs["crontab"]
        self.__enabled = kwargs["enabled"]

        self.__test_type = kwargs["test_type"]
        if self.__test_type == 'module':
            self.__task = CELERY_TEST_TASK['modle']
        elif self.__test_type == 'suite':
            self.__task = CELERY_TEST_TASK['suite']
        elif self.__test_type == 'project':
            self.__task = CELERY_TEST_TASK['project']
        self.__index = kwargs["params"].get('index')
        self.__config_id = kwargs["params"].get('config_id')

        self.__project = kwargs["belong_project"]
        self.__email = {
            "index": self.__index,
            "config_id": self.__config_id,
            "strategy": kwargs["strategy"],
            "copy": kwargs["copy"],
            "receiver": kwargs["receiver"],
            "crontab": self.__crontab,
            "project": self.__project
        }
        self.__crontab_time = None

    def format_crontab(self):
        """
        格式化时间
        """
        crontab = self.__crontab.split(' ')
        if len(crontab) > 5:
            return response.TASK_TIME_ILLEGAL
        try:
            self.__crontab_time = {
                'day_of_week': crontab[4],
                'month_of_year': crontab[3],
                'day_of_month': crontab[2],
                'hour': crontab[1],
                'minute': crontab[0]
            }
        except Exception:
            return response.TASK_TIME_ILLEGAL

        return response.TASK_ADD_SUCCESS

    def add_task(self):
        """
        add tasks
        """
        if self.__name:
            if PeriodicTask.objects.filter(name__exact=self.__name).count() > 0:
                logger.info("{name} tasks exist".format(name=self.__name))
                return response.TASK_HAS_EXISTS
        else:
            return response.TASK_NAME_EMPTY

        if not self.__email.get('index', None):
            return response.TASK_ITEM_EMPTY

        if self.__email["strategy"] == '始终发送' or self.__email["strategy"] == '仅失败发送':
            if self.__email["receiver"] == '':
                return response.TASK_EMAIL_ILLEGAL

        resp = self.format_crontab()
        if resp["success"]:
            task, created = PeriodicTask.objects.get_or_create(name=self.__name, task=self.__task)
            crontab = CrontabSchedule.objects.filter(**self.__crontab_time).first()
            if crontab is None:
                crontab = CrontabSchedule.objects.create(**self.__crontab_time)
            task.crontab = crontab
            task.enabled = self.__enabled
            task.args = json.dumps(self.__args, ensure_ascii=False)
            task.kwargs = json.dumps(self.__email, ensure_ascii=False)
            task.description = self.__project
            task.save()
            logger.info("{name} tasks save success".format(name=self.__name))
            return response.TASK_ADD_SUCCESS
        else:
            return resp


class ScheduleTaskView(GenericViewSet):
    """
    定时任务增删改查
    """
    queryset = PeriodicTask.objects
    serializer_class = PeriodicTaskSerializer
    pagination_class = MyPageNumberPagination

    def list(self, request):
        """
        查询项目信息
        """
        project = request.query_params.get("belong_project")
        logger.info("Query {project}".format(project=project))
        if project:
            schedule = self.get_queryset().filter(description=project).order_by('-date_changed')
        else:
            schedule = self.get_queryset().order_by('-date_changed')
        page_schedule = self.paginate_queryset(schedule)
        serializer = self.get_serializer(page_schedule, many=True)
        return self.get_paginated_response(serializer.data)

    def create(self, request):
        """新增定时任务{
            name: str
            crontab: str
            switch: bool
            data: [int,int]
            strategy: str
            receiver: str 邮件收件
            copy: str 邮件抄送
            project: int
        }
        """
        task = Task(**request.data)
        resp = task.add_task()
        return Response(resp)

    def update(self, request):
        """
        编辑定时任务
        """
        task = Task(**request.data)
        resp = task.add_task()
        return Response(resp)

    def retrieve(self, request, *args, **kwargs):
        """
        编辑项目
        """
        task_obj = PeriodicTask.objects.get(id=kwargs["pk"])

        task_form: {
            'id': task_obj.id,
            'name': task_obj.name,
            'belong_project': task_obj.get('description'),
            'test_type': task_value_to_key(task_obj.get('task')),
            'params': {
                'index': task_obj.get('kwargs').get('index', ''),
                'config_id': task_obj.get('kwargs').get('config_id', ''),
            },
            'enabled': task_obj.get('enabled'),
            'strategy': task_obj.get('kwargs').get('strategy', '始终发送'),
            'crontab': task_obj.get('kwargs').get('crontab', ''),
            'receiver': task_obj.get('kwargs').get('receiver', ''),
            'copy': task_obj.get('kwargs').get('copy', ''),
        }
        response.SUCCESS_INFO['data'] = task_form
        return Response(response.SUCCESS_INFO)

    def enable(self, request, **kwargs):
        """删除任务
        """
        task_obj = PeriodicTask.objects.get(id=kwargs["pk"])
        task_obj.enabled = not task_obj.enabled
        task_obj.save()
        return Response(response.TASK_DEL_SUCCESS)

    def destroy(self, request, **kwargs):
        """删除任务
        """
        try:
            task_obj = PeriodicTask.objects.get(id=kwargs["pk"])
            task_obj.enabled = False
            task_obj.delete()
            return Response(response.TASK_DEL_SUCCESS)
        except celery_models.PeriodicTask.DoesNotExist:
            return 'error'
